﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;

namespace EntityDesigner2
{
    public partial class FrmImport : Form
    {
        // 私有变量
        private string _localPath;
        private string _localConfigPath;
        private string _path;
        private string _pathData;
        private string _pathTool;
        private const string PostgresEFCore_3_1 = "Ref-PostgresEFCore-3.1\\Ref-PostgresEFCore-3.1.exe";
        private List<TableInfo> tableInfos;

        public FrmImport()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 表格信息
        /// </summary>
        public Table Table { get; set; }

        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog f = new OpenFileDialog())
            {
                f.Title = "加载 dll ...";
                f.Filter = "动态链接库(*.dll)|*.dll";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    LoadDll(f.FileName);
                }
            }
        }

        private void listBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void ShowList()
        {
            string key = this.textBox2.Text.Trim();
            this.listBox1.Items.Clear();
            for (int i = 0; i < tableInfos.Count; i++)
            {
                string name = tableInfos[i].TableClassNamespace + "." + tableInfos[i].TableClassName + " - " + tableInfos[i].TableDescription;
                if (string.IsNullOrWhiteSpace(key))
                {
                    this.listBox1.Items.Add(name);
                }
                else
                {
                    if (name.Contains(key)) this.listBox1.Items.Add(name);
                }
            }
        }

        // 加载DLL
        public void LoadDll(string path)
        {
            _localPath = AppDomain.CurrentDomain.BaseDirectory;
            if (!_localPath.EndsWith("\\")) _localPath += "\\";
            _pathTool = _localPath + PostgresEFCore_3_1;
            if (!System.IO.File.Exists(_pathTool))
            {
                MessageBox.Show($"未找到工具'{_pathTool}'");
                return;
            }
            this.textBox1.Text = path;
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = _pathTool;
            info.Arguments = $"--path:\"{path}\"";
            info.UseShellExecute = false;
            info.CreateNoWindow = true;
            info.RedirectStandardOutput = true;
            var pro = Process.Start(info);
            List<char> sb = new List<char>();
            char[] buffer = new char[4096];
            using (StreamReader reader = pro.StandardOutput)
            {
                while (!reader.EndOfStream)
                {
                    int res = reader.ReadBlock(buffer, 0, buffer.Length);
                    for (int i = 0; i < res; i++)
                    {
                        sb.Add(buffer[i]);
                    }
                }
            }
            string json = new string(sb.ToArray());
            JsonResponse<List<TableInfo>> response = JsonConvert.DeserializeObject<JsonResponse<List<TableInfo>>>(json);
            if (response.IsSuccessed)
            {
                tableInfos = response.Result;
                ShowList();
            }
            else
            {
                MessageBox.Show(response.Message);
            }
        }

        private void listBox1_DragDrop(object sender, DragEventArgs e)
        {
            var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
            if (files.Length > 0)
            {
                // 自动保存
                LoadDll(files[0]);
            }
        }

        private void FrmImport_Load(object sender, EventArgs e)
        {
        }

        private string ConvertVarType(string name)
        {
            switch (name)
            {
                case "System.String": return "string";
                case "System.Double": return "double";
                case "System.Int32": return "int";
                case "System.Int64": return "long";
                case "System.Boolean": return "bool";
                default:
                    return name.Split('.').Last();
            }
        }

        private string GetDbType(string name)
        {
            int idx = name.IndexOf('(');
            if (idx > 0)
            {
                return name.Substring(0, idx);
            }
            else
            {
                return name;
            }
        }

        private int GetDbLength(string name)
        {
            int idx1 = name.IndexOf('(');
            int idx2 = name.IndexOf(',');
            if (idx2 > idx1)
            {
                int len = 0;
                int.TryParse(name.Substring(idx1 + 1, idx2 - idx1).Trim(), out len);
                return len;
            }
            else
            {
                return 0;
            }
        }

        private int GetDbFloat(string name)
        {
            int idx1 = name.IndexOf(',');
            int idx2 = name.IndexOf(')');
            if (idx2 > idx1)
            {
                int len = 0;
                int.TryParse(name.Substring(idx1 + 1, idx2 - idx1).Trim(), out len);
                return len;
                //return int.Parse(name.Substring(idx1 + 1, idx2 - idx1).Trim());
            }
            else
            {
                return 0;
            }
        }

        private void Import()
        {
            if (tableInfos is null) { MessageBox.Show("请先加载一个dll"); return; }
            if (this.listBox1.SelectedIndex < 0) { MessageBox.Show("请先选择一个表"); return; }
            string tableName = (string)this.listBox1.Items[this.listBox1.SelectedIndex];
            for (int i = 0; i < tableInfos.Count; i++)
            {
                var table = tableInfos[i];
                string name = tableInfos[i].TableClassNamespace + "." + tableInfos[i].TableClassName + " - " + tableInfos[i].TableDescription;
                if (name == tableName)
                {
                    Table tab = new Table();
                    tab.Properties = new Dictionary<string, string>();
                    tab.Columns = new List<TableColumn>();
                    tab.Properties["Name"] = table.TableClassName;
                    tab.Properties["DbName"] = table.TableName;
                    tab.Properties["Abbr"] = table.TableAbbr;
                    tab.Properties["Text"] = table.TableDescription;
                    tab.Properties["Schema"] = table.TableSchema;
                    tab.Properties["Inherit"] = table.TableInherit;
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        var column = table.Columns[j];
                        tab.Columns.Add(new TableColumn()
                        {
                            ColumnName = column.ColumnPropertyName,
                            ColumnNullable = column.ColumnNullable,
                            ColumnPrimaryKey = column.ColumnPrimaryKey,
                            ColumnRequired = column.ColumnRequired,
                            ColumnText = column.ColumnDescription,
                            ColumnType = GetDbType(column.ColumnType),
                            ColumnTypeFloat = GetDbFloat(column.ColumnType),
                            ColumnTypeLength = GetDbLength(column.ColumnType),
                            ColumnDbName = column.ColumnName,
                            ColumnVarType = ConvertVarType(column.ColumnPropertyType),
                            ColumnMake = true,
                        });
                        if (column.ColumnPropertyName == "TenantId")
                        {
                            if (column.ColumnNullable)
                            {
                                tab.Properties["Inherit"] += ", IMayHaveTenant";
                            }
                            else
                            {
                                tab.Properties["Inherit"] += ", IMustHaveTenant";
                            }
                        }
                    }
                    this.Table = tab;
                }
            }
            this.DialogResult = DialogResult.OK;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Import();
        }

        private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Import();
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (tableInfos is null) return;
            ShowList();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (tableInfos is null) { MessageBox.Show("请先加载一个dll"); return; }
            if (this.listBox1.SelectedIndex < 0) { MessageBox.Show("请先选择一个表"); return; }
            string tableName = (string)this.listBox1.Items[this.listBox1.SelectedIndex];
            for (int i = 0; i < tableInfos.Count; i++)
            {
                var table = tableInfos[i];
                string name = tableInfos[i].TableClassNamespace + "." + tableInfos[i].TableClassName + " - " + tableInfos[i].TableDescription;
                if (name == tableName)
                {
                    StringBuilder sb = new StringBuilder();
                    string tabFullName = (string.IsNullOrWhiteSpace(table.TableSchema) ? "" : table.TableSchema + ".") + table.TableName;
                    string tabPrimaryKey = "";
                    sb.AppendLine($"-- 添加{table.TableDescription}表");
                    sb.AppendLine($"CREATE TABLE {tabFullName}(");
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        var col = table.Columns[j];
                        if (col.ColumnPrimaryKey || col.ColumnName == "id")
                        {
                            var colType = col.ColumnType;
                            switch (col.ColumnType)
                            {
                                case "varchar":
                                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                                    break;
                                case "decimal":
                                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                                    break;
                            }
                            sb.AppendLine($"    -- {col.ColumnDescription}");
                            sb.AppendLine($"    \"{col.ColumnName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")},");
                            tabPrimaryKey = col.ColumnName;
                        }
                    }
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        var col = table.Columns[j];
                        if (!col.ColumnPrimaryKey && col.ColumnName != "id")
                        {
                            var colType = col.ColumnType;
                            switch (col.ColumnType)
                            {
                                case "varchar":
                                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                                    break;
                                case "decimal":
                                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                                    break;
                            }
                            sb.AppendLine($"    -- {col.ColumnDescription}");
                            sb.Append($"    \"{col.ColumnName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")}");
                            if (!string.IsNullOrWhiteSpace(tabPrimaryKey) || (string.IsNullOrWhiteSpace(tabPrimaryKey) && i < table.Columns.Count - 1)) sb.Append(',');
                            sb.AppendLine();
                        }
                    }
                    if (!string.IsNullOrWhiteSpace(tabPrimaryKey)) sb.AppendLine($"    CONSTRAINT \"PK_{table.TableName}\" PRIMARY KEY ({tabPrimaryKey})");
                    sb.AppendLine($");");
                    sb.AppendLine();
                    // 生成描述
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        var col = table.Columns[j];
                        sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnName} IS '{col.ColumnDescription}';");
                    }
                    sb.AppendLine();
                    //// 生成索引
                    //for (int j = 0; j < table.Columns.Count; j++)
                    //{
                    //    var col = table.Columns[j];
                    //    if (col.ColumnPrimaryKey)
                    //    {
                    //        sb.AppendLine($"CREATE UNIQUE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} USING btree ({col.ColumnDbName});");
                    //    }
                    //    else
                    //    {
                    //        sb.AppendLine($"CREATE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} ({col.ColumnDbName});");
                    //    }
                    //}
                    FrmText frm = new FrmText();
                    frm.Text = $"Sql生成 - 表创建 - [{table.TableDescription}({table.TableClassName})]";
                    frm.ContentTextBox.Text = sb.ToString();
                    frm.Show();


                    //for (int j = 0; j < table.Columns.Count; j++)
                    //{
                    //    var column = table.Columns[j];
                    //    tab.Columns.Add(new TableColumn()
                    //    {
                    //        ColumnName = column.ColumnPropertyName,
                    //        ColumnNullable = column.ColumnNullable,
                    //        ColumnPrimaryKey = column.ColumnPrimaryKey,
                    //        ColumnRequired = column.ColumnRequired,
                    //        ColumnText = column.ColumnDescription,
                    //        ColumnType = GetDbType(column.ColumnType),
                    //        ColumnTypeFloat = GetDbFloat(column.ColumnType),
                    //        ColumnTypeLength = GetDbLength(column.ColumnType),
                    //        ColumnDbName = column.ColumnName,
                    //        ColumnVarType = ConvertVarType(column.ColumnPropertyType),
                    //        ColumnMake = true,
                    //    });
                    //    if (column.ColumnPropertyName == "TenantId")
                    //    {
                    //        if (column.ColumnNullable)
                    //        {
                    //            tab.Properties["Inherit"] += ", IMayHaveTenant";
                    //        }
                    //        else
                    //        {
                    //            tab.Properties["Inherit"] += ", IMustHaveTenant";
                    //        }
                    //    }
                    //}
                    //this.Table = tab;
                }
            }
        }
    }
}
